package com.jichaoyun.util;

import cn.com.agree.security.EncryptAndDecrypt;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jichaoyun.common.enums.MyExceptiontType;
import com.jichaoyun.common.ex.MyException;
import com.jichaoyun.model.vo.ChargeBankVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.Base64;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

/**
 * 用于加密和解密数据的工具类，用于银行充值业务
 *
 * createTime:2024/3/26
 * author:ywqqq
 */
@Slf4j
public class EncodeUtil {

  private static final String RSA_PRIVATE_KEY_STRING = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1bJOgkYTqGRmP\n"
      + "uZxemarqu69BpKOaoiq3y3h3/Fo/p+HwdI5xExqTEDWqzrVcOPeF2ZdfHrTTlWj5\n"
      + "gPcAuoswfWcbpu5FkoRACsvlKYFDTiOrCPPg2EiPxfh4Q1PKZbVgetR3Yt61OxbW\n"
      + "2k93OO3HhhhyPZSKwMJdKK+Crwnfb7DyOQgBr8162bEmIcOnUcR0c8IWoHW8fWtG\n"
      + "OGXyACbm0YkBlOozXZrkKoCEHkIwViPqkmL4xjuAiwI77xTVjUIiISg14+sY3LEc\n"
      + "cutHXk24w+SiRMg/Xumyc5azxmHdvcIz76McJ2KIOyQLZE3O9xU+bMlf6QfUQWuZ\n"
      + "zIcxcb3BAgMBAAECggEAQIlkJn09a80L872SK3C8hQ3ItTAs5qgDTCg8LWp+bCB7\n"
      + "Vf8QYJbsIB5nCODJUQoOuvWBTFvu9Ukz83V16DNzqgch84s5PVR2aRWuHFHcYqXc\n"
      + "OE5R+szVWxeQYK+KkfgGQlDPXby0/oELidhU5lNA+nXwIktXmNgjC+KaNIGxoGJQ\n"
      + "KeognGxGG1cnNu4mtQbYH8wQWOpitjmhRO4Pqqlolq47QxCOBZSg2OVVUFqh3/BY\n"
      + "pj4v2DFp064Lx56sPMk2bqPqy8OcdU62NA6y5YFm4KqO9HWliT/TFAtvTQiZviNf\n"
      + "1HhYP7o3UrNCK/gtasjwqcm7z7afFsPxaERVQQ1XsQKBgQDogkEu4Aw4AyjaYsmT\n"
      + "eE6MB3x9/8kM01Nnb8ofCErKNbwFUHIdLQEKX7ulA7grgI6sJ1Ng7vkhxK9te+dP\n"
      + "T4LECgBKeoYBP7M6nYVF3O0B5wnIT0uxGj0sfHqz6TrJotK/VCKkt3xSXA02ICVq\n"
      + "9129aHv6cRXLW62FaqP8iDKyNQKBgQDHwQmkgSGKg0MLeI9T6fJwlh7fctfaZ1fP\n"
      + "sZX9HNibu4/X5uaikiGuAatZdQBIAcs3hHKVshI29taL9UASnbuoVvrSu4FQUugL\n"
      + "IEuOYBst0YN5LeIx8JhA39qFB8Ej9IodgT3QydHvczsm4saE5nD+dt+xf7nDMU+K\n"
      + "YXnk5hMO3QKBgFSZgGoz7345+BVuOHZGIh5lYvDdryPRiNlsHZkpBT2KS72LRdpD\n"
      + "08sYhkhGkC6T+lW9gWMV0ORukn49xS5gee4mzXBMIJI3wVkkk6eV+U7l5/NQlvP7\n"
      + "3iJfsK3hwRg4/IHNdUWF1eCJyezVyYegNiWC7Ql1OD7kPsD6ymxKile5AoGBAJ4k\n"
      + "sOqhJRnRE8pIF0j7BWqnHygOdt+9Q2L2GGX8aWzZ0GbAskVw5eMqBStcmu1nJij8\n"
      + "3e6vvQXw5CiH8MMMR55dxlQCCL279WOhnM/KPJpIrgrJDbQ144Qw9YKugfViS9pS\n"
      + "EMt0jJVDKEh/72UWP8zl9fFDyqDDMFLBG0zh7aKtAoGAPf8C5JsEODkG53mVEvfE\n"
      + "ARz4s5zILj+q72nWrXYFI0vJW56W087y6+/uGMZ4CjLC/sTCg3MyJGEWg+qun6KZ\n"
      + "c+rWCvKeZ77k7n5G9E7cLTyemsAPlHsSiou/PwYdN5ULaQFtU7ddkyedjYH1E3KZ\n"
      + "ChWiY+XXoTJwvjNNMkYr8tY=";

  private static final String RSA_PUBLIC_KEY_STRING = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtWyToJGE6hkZj7mcXpmq\n"
      + "6ruvQaSjmqIqt8t4d/xaP6fh8HSOcRMakxA1qs61XDj3hdmXXx6005Vo+YD3ALqL\n"
      + "MH1nG6buRZKEQArL5SmBQ04jqwjz4NhIj8X4eENTymW1YHrUd2LetTsW1tpPdzjt\n"
      + "x4YYcj2UisDCXSivgq8J32+w8jkIAa/NetmxJiHDp1HEdHPCFqB1vH1rRjhl8gAm\n"
      + "5tGJAZTqM12a5CqAhB5CMFYj6pJi+MY7gIsCO+8U1Y1CIiEoNePrGNyxHHLrR15N\n"
      + "uMPkokTIP17psnOWs8Zh3b3CM++jHCdiiDskC2RNzvcVPmzJX+kH1EFrmcyHMXG9\n"
      + "wQIDAQAB";

  private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  private static final Random RANDOM = new Random();
  private static final int KEY_SIZE = 16; // 16 bytes for AES-128

  public static String generateRandomString() {
    StringBuilder stringBuilder = new StringBuilder(KEY_SIZE);
    for (int i = 0; i < KEY_SIZE; i++) {
      int index = RANDOM.nextInt(CHARACTERS.length());
      stringBuilder.append(CHARACTERS.charAt(index));
    }
    return stringBuilder.toString();
  }

//  public static void main(String[] args) throws Exception {
//    // 创建交易信息转换为JSON字符串
//    ChargeBankVo vo = new ChargeBankVo();
//    vo.setSend_id("62223584059094");
//    vo.setReceive_id("62223584059094");
//    vo.setAmount(new Double(100));
//    vo.setReversal(true);
//    vo.setTime(new Timestamp(System.currentTimeMillis()));
//    JSONObject object = encode_ningdong(vo);
//    System.out.println(object.toJSONString());
//    ChargeBankVo json_result= decode_jichao(object);
//    System.out.println("Decrypted JSON: " + json_result.toString());
//
//  }

  private static String encrypt_rsa(byte[] keyBytes,PrivateKey rsaPrivateKey) throws Exception {
    Cipher rsaEncryptCipher = Cipher.getInstance("RSA");
    rsaEncryptCipher.init(Cipher.ENCRYPT_MODE, rsaPrivateKey);
    byte[] encryptedAesKey = rsaEncryptCipher.doFinal(keyBytes);
    return Base64.getEncoder().encodeToString(encryptedAesKey);
  }

  private static String encrypt_aes(String plainText, SecretKeySpec keySpec) throws Exception {
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, keySpec);
    byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
    return Base64.getEncoder().encodeToString(encryptedBytes);
  }

  private static SecretKeySpec decrypt_rsa(String encryptedBase64String,PublicKey rsaPublicKey) throws Exception{
    byte[] decryptedAesKeyBase64 = Base64.getDecoder().decode(encryptedBase64String);
    Cipher rsaDecryptCipher = Cipher.getInstance("RSA");
    rsaDecryptCipher.init(Cipher.DECRYPT_MODE, rsaPublicKey);
    byte[] decryptedAesKey = rsaDecryptCipher.doFinal(decryptedAesKeyBase64);
    return new SecretKeySpec(decryptedAesKey, "AES");
  }

  private static String decrypt_aes(String encryptedBase64String, SecretKeySpec keySpec) throws Exception {
    byte[] encryptedBytes = Base64.getDecoder().decode(encryptedBase64String);
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, keySpec);
    byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
    return new String(decryptedBytes, "UTF-8");
  }

  public static JSONObject encode_ningdong(ChargeBankVo data) throws Exception{ //交易信息数据
    // 随机产生16位字符串转换为AES对称密钥
    String privateKey = generateRandomString();
    byte[] keyBytes = privateKey.getBytes(StandardCharsets.UTF_8);
    SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
    // 读取字符串转换为RSA私钥
    byte[] privateKeyBytes = Base64.getDecoder().decode(
        RSA_PRIVATE_KEY_STRING.replaceAll("\\s", ""));
    PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    PrivateKey rsaPrivateKey = kf.generatePrivate(pkcs8KeySpec);
    String jsonString = JSON.toJSONString(data);
    // AES加密
    String encryptedData = encrypt_aes(jsonString, secretKeySpec);
    // RSA加密
    String encryptedAesKeyBase64 = encrypt_rsa(secretKeySpec.getEncoded(),rsaPrivateKey);
    // 创建传输数据，SHA-256签名
    long currentTimeMillis = Instant.now().toEpochMilli();
    Timestamp now = new Timestamp(currentTimeMillis);
    UUID uuid = UUID.randomUUID();
    JSONObject object =  new JSONObject();
    object.put("data",encryptedData);
    object.put("randomKey", encryptedAesKeyBase64);
    // 转换为字节数组
    byte[] jsonBytes = object.toJSONString().getBytes(StandardCharsets.UTF_8);
    // 对JSON字节进行SHA-256签名
    byte[] sha256Signature = DigestUtils.sha256(jsonBytes);
    // 对签名值进行Base64编码
    String base64EncodedSignature = Base64.getEncoder().encodeToString(sha256Signature);
    object.put("signature",base64EncodedSignature);
    object.put("uuid",uuid.toString());
    object.put("timestamp", now);
    return object;
  }

//  public static ChargeBankVo decode_jichao(Map<String, Object> json) throws Exception {//signature:签名 jsonBytes:数据
//    // 读取字符串转换为RSA公钥
//    String signature = json.get("signature").toString();
//    byte[] signatureBase64 = Base64.getDecoder().decode(signature);
//    String data_json = (String) json.get("data");
//    String randomKey = (String) json.get("randomKey");
//    JSONObject json_new = new JSONObject();
//    json_new.put("data", data_json);
//    json_new.put("randomKey", randomKey);
//    byte[] data_bytes = json_new.toJSONString().getBytes(StandardCharsets.UTF_8);
//    if (Arrays.equals(signatureBase64, DigestUtils.sha256(data_bytes))) {
//      String aesKey = (String) json.get("randomKey");
////      String data = (String) json.get("data");
//      byte[] publicKeyBytes = Base64.getDecoder().decode(
//          RSA_PUBLIC_KEY_STRING.replaceAll("\\s", ""));
//      X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes);
//      KeyFactory kf = KeyFactory.getInstance("RSA");
//      PublicKey rsaPublicKey = kf.generatePublic(x509KeySpec);
//      // RSA解密
//      SecretKeySpec secretKeySpec_new = decrypt_rsa(aesKey, rsaPublicKey);
//      // AES解密
//      String decryptedJsonString = decrypt_aes(data_json, secretKeySpec_new);
//
//      ChargeBankVo vo = JSONObject.toJavaObject(JSONObject.parseObject(decryptedJsonString),
//          ChargeBankVo.class);
//      return vo;
//    } else {
//      throw new MyException(MyExceptiontType.Other, "验签不通过");
//    }
//  }

  public static ChargeBankVo decode_jichao(Map<String, Object> json) throws Exception{
    byte[] data = JSON.toJSONString(json).getBytes();
    Map<String,Object> result = EncryptAndDecrypt.Decrypt(data,"D:\\test_c.jks","111111","test_c_private","123456");
    log.info("原始结果："+result.toString());
    if(result.get("returnCode").equals("0000")){
      byte[] byteData = (byte[]) result.get("jsonData");
      String stringData = new String(byteData);
      log.info("解密结果："+stringData);
      ChargeBankVo vo = JSONObject.toJavaObject(JSONObject.parseObject(stringData),ChargeBankVo.class);
      return vo;
    }else{
      throw new MyException(MyExceptiontType.Other,"验签不通过");
    }
  }


}
